<?php

header('Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Pragma: no-cache');

/**
 * This script is used by all clients for location update (web and non-web based ones too).
 *
 * This script is used to update the currently logged in user's location.
 * Parameters:
 * [MANDATORY]  [lon]       [integer]   The longitude part of the location.
 * [MANDATORY]  [lat]       [integer]   The latitude part of the location.
 * [OPTIONAL]   [data]      [string]    Optional text (stored in the association object) 
 * [OPTIONAL]   [publish]   [boolean]   Whether to publish on Facebook or not.
 * [OPTIONAL]   [next]      [string]    URL where to redirect the user after finishing this script
 * 
 * If <code>publish</code> is true and <code>next</code> is undefined, 
 * then the user after filling out the publishing form, will be redirected to the index.php/main.php.
 * If <code>publish</code> is false and <code>next</code> is undefined,
 * then the user won't be redirected.
 * So, when calling from JavaScript only the lon and lat (optionally also data) parameters have to be defined.
 * 
 */
include_once './log4php/Logger.php';

include_once './config.php';
include_once './User.php';
include_once './Location.php';
include_once './Situare.php';
include_once './Error.php';
include_once './Utils.php';

// set up logging
Logger::configure('./log4j.properties');

$log = Logger::getLogger(basename(__FILE__));
$log->debug('[START] ' . basename(__FILE__));

try {
    $situare = new Situare();
    $inputArray = Utils::getInputParameters();
    $format = Utils::getInputParameterValue($inputArray, PARAM_FORMAT, FORMAT_TEXT);
    $api = Utils::getInputParameterValue($inputArray, PARAM_API, NULL);

    if (!$situare->isValidSession()) {
        $log->debug('$_COOKIE[] = ' . Utils::toString($_COOKIE));
        $log->debug('$_POST[] = ' . Utils::toString($_POST));
        $log->debug('$_GET[] = ' . Utils::toString($_GET));
        throw new SituareException(
                "Not found valid session data!",
                ERROR_SESSION_INVALID_OR_MISSING);
    }

    $action = Utils::getInputParameterValue($inputArray, PARAM_ACTION, NULL);
    $next = Utils::getInputParameterValue($inputArray, PARAM_NEXT, NULL);
    
    $log->debug("action: " . $action);

    if ($action == NULL || $action == 'locationupdate') {
        $lon = Utils::getLongitude($inputArray);
        $lat = Utils::getLatitude($inputArray);
        $data = Utils::getInputParameterValue($inputArray, PARAM_DATA, '');
        $publish = getPublish($inputArray);
        $address = getAddress($lon, $lat);
        $log->debug("Address ($lon, $lat): $address");

        // update the position data in the FB database
        $situare->updateLocation($lon, $lat, $data, $address);

        if ($publish) {    // publish on Facebook
            $log->debug('We are going to publish it on facebook!');

            $nextUrl = urlencode(HOME_URL . "?action=locationpublish&data=$data&address=$address");
            $log->debug("nextUrl: " . $next);
            try {
                $situare->publishPositionUpdate($data, $address, $nextUrl);
            } catch (Exception $e) {
                if ($e->getCode() == 200) { // missing permission to publish on wall
                    throw new Exception(
                            "Publishing to FB wall not permitted!",
                            ERROR_UPDATELOCATION_MISSING_POST_PERMISSION);
                }
                else {
                    throw $e;   // propagate
                }
            }
        }
        else if ($next != NULL) {
            $log->debug('Redirecting to: ' . $next);
            header("Location: $next");
        }
        // do update
        // do publish if required
    }
    else if ($action == 'locationpublish') {
        // check whether permission wan not denied
        checkPublishAccessDenied();

        // publish
        $data = Utils::getInputParameterValue($inputArray, PARAM_DATA, '');
        $address = Utils::getInputParameterValue($inputArray, PARAM_ADDRESS, NULL);
        if ($address == NULL) {
            // if the 'address' param was not sent, but the 'lon' and 'lat' params were
            // then try to discover the address from lon and lat values
            $lon = Utils::getInputParameterValue($inputArray, PARAM_LON, NULL);
            $lat = Utils::getInputParameterValue($inputArray, PARAM_LAT, NULL);
            if ($lon != NULL && $lat != NULL) {
                $address = getAddress($lon, $lat);
                $log->debug("Address ($lon, $lat): $address");
            }
        }
        $nextUrl = urlencode(HOME_URL . "?action=locationpublish&data=$data&address=$address");
        $log->debug("nextUrl: " . $next);
        try {
            $situare->publishPositionUpdate($data, $address, $nextUrl);
        } catch (Exception $e) {
            if ($e->getCode() == 200) { // missing permission to publish on wall
                throw new Exception(
                        "Publishing to FB wall not permitted!",
                        ERROR_UPDATELOCATION_MISSING_POST_PERMISSION);
            }
            else {
                throw $e;   // propagate
            }
        }
    }
    else if ($action == 'locationpublishdenied') {
        // do nothing, just finish the script
    }
    else {
        throw new Exception(
                "Unsupported action: $action",
                ERROR_GENERAL);
    }

    if ($api == API_2_0) {
        echo Situare::getApi20Response("Executed successfully!");
    }
    
    $log->debug('[ END ] ' . basename(__FILE__));
} catch (Exception $e) {
    $log->error("Exception:");
    $log->error("Code: " . $e->getCode());
    $log->error("Message: " . $e->getMessage());
    $log->error("Location: " . $e->getFile() . " at line " . $e->getLine());
    $log->error("Trace: " . $e->getTraceAsString());

    if ($api == API_2_0) {
        echo Situare::getApi20Response($e);
    }
    else if ($format == FORMAT_JSON) {
        echo getExceptionAsJson($e);
    }
    else {
        if ($e->getCode() == ERROR_UPDATELOCATION_MISSING_POST_PERMISSION) {
            $prompt_perm_url = $situare->getPromptPermissionsUrl($nextUrl, 'publish_stream');
            $log->debug("prompt_perm_url: " . $prompt_perm_url);
            header("Location: $prompt_perm_url");
        }
        else if ($e->getCode() == ERROR_UPDATELOCATION_DENIED_POST_PERMISSION) {
            header("Location: " . HOME_URL);
        }
        else {
            // TODO return complette valid XHTML page
            echo "\n<br/><b>An error occured:</b> ";
            echo "\n<br/><b>Code:</b> " . $e->getCode();
            echo "\n<br/><b>Message:</b> " . $e->getMessage();
            echo "\n<br/><b>Location:</b> " . $e->getFile() . " at line " . $e->getLine();
            echo "\n<br/><b>Trace:</b> " . $e->getTraceAsString();

            echo "\n<br/><br/><input type='submit' onclick='window.location=\"" . HOME_URL . "\"' value='Login'/>";
        }
    }

    exit();
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
//

/**
 * 
 * @return unknown_type
 */
function getLon($inputArray) {
    if (!isset($inputArray[PARAM_LON])) {
        throw new Exception(
                'Missing argument: ' . PARAM_LON,
                ERROR_UPDATELOCATION_LONLAT_MISSING);
    }

    if (!is_numeric($inputArray[PARAM_LON]) || $inputArray[PARAM_LON] > 180.0 || $inputArray[PARAM_LON] < -180.0) {
        throw new Exception(
                'Wrong lon value: ' . $inputArray[PARAM_LON] . '. Longitude must be between -180 and 180!',
                ERROR_UPDATELOCATION_LONLAT_INVALID);
    }

    return $inputArray[PARAM_LON];
}

/**
 * 
 * @return string
 */
function getLat($inputArray) {
    if (!isset($inputArray[PARAM_LAT])) {
        throw new Exception(
                'Missing argument: ' . PARAM_LAT,
                ERROR_UPDATELOCATION_LONLAT_MISSING);
    }

    if (!is_numeric($inputArray[PARAM_LAT]) || $inputArray[PARAM_LAT] > 90.0 || $inputArray[PARAM_LAT] < -90.0) {
        throw new Exception(
                'Wrong lat value: ' . $inputArray[PARAM_LAT] . '. Latitude must be between -90 and 90!',
                ERROR_UPDATELOCATION_LONLAT_INVALID);
    }

    return $inputArray[PARAM_LAT];
}

/**
 * 
 * @return unknown_type
 */
function getPublish($inputArray) {
    return (isset($inputArray[PARAM_PUBLISH])
    && strcasecmp('false', $inputArray[PARAM_PUBLISH]) != 0
    && strcasecmp('0', $inputArray[PARAM_PUBLISH]) != 0) ? true : false;
}

///**
// *
// * @param <type> $name
// * @param <type> $defaultValue
// * @return <type>
// */
//function getRequestParamValue($inputArray, $name, $defaultValue=NULL) {
//    return isset($inputArray[$name]) ? $inputArray[$name] : $defaultValue;
//}

/**
 * Checks the request params, it the parameter signalizing permission denied
 * exception is thrown.
 * The parameters signalizing permission deny are: 'error', 'error_reason' and 'error_description'.
 *
 * @throws Exception ERROR_UPDATELOCATION_DENIED_POST_PERMISSION if the permission was denied is detected
 */
function checkPublishAccessDenied() {
    if (isset($_REQUEST['error'])
            && isset($_REQUEST['error_reason'])
            && isset($_REQUEST['error_description'])) {
        throw new Exception(
                $_REQUEST['error_description'],
                ERROR_UPDATELOCATION_DENIED_POST_PERMISSION);
    }
}

function getAddress($lon, $lat) {
    try {
        $address = Location::getLocationAddress($lon, $lat);
    } catch (Exception $e) {
        $address = "";
    }
    return $address;
}

?>